#include "sys.h"
#include "net.h"
#include "log.h"
#include "process_monitor.h"
#include "platform.h"
#include "onu_comm.h"

static char Storage_path[64] = {0};
static int Zombie_State_Count = 0;
static char Svr_host[64] = "10.0.0.210";
static uint16_t Tcp_port = 18087, Udp_port = 17087;
static OPT_T opts[] = {
    { "-a", Svr_host, OPT_STRING, "server address." },
    { "-n", &Tcp_port, OPT_SHORT, "tcp port." },
    { "-u", &Udp_port, OPT_SHORT, "udp port." },
    { "-s", &Storage_path, OPT_STRING, "storage path." },
};

int get_process_state_count(char *exec_name, char *state){
	int count = 0;
    int tmp_pid = 0;
    char tmp_name[32] = {0}, tmp_stat[32] = {0};
    DIR *dir = NULL;
    struct dirent *dptr = NULL;

    if(!exec_name){
    	return 0;
    }

    dir = opendir("/proc/");
    if(!dir){
        log_syserr("opendir error.");
        return 0;
    }

    while((dptr = readdir(dir)) != NULL){
        if(strcmp(dptr->d_name, ".") == 0 || strcmp(dptr->d_name, "..") == 0){
            continue;
        }
        if((tmp_pid = atoi(dptr->d_name)) > 0){
            bzero(tmp_name, sizeof(tmp_name));
            get_exec_name_by_pid(tmp_pid, tmp_name);
            get_exec_stat_by_pid(tmp_pid, tmp_stat);
            if(!strcmp(tmp_name, exec_name) && !strcmp(tmp_stat, state)){
                count++;
            }
        }

    }
    closedir(dir);
    return count;
}
void killall_process(char *pro_name){
    system_killall(pro_name);
}
static void start_onuProbe(){
    char cmd[512] = {0};

    sprintf(cmd, "./%s -a %s -n %d -u %d &", ONU_PROBE_EXE, Svr_host, Tcp_port, Udp_port);
    log_trace("%s", cmd);
    system(cmd);
}
static void _backup_log(){
    #define _BACKUP_LOG_FILE "backup.log"

    system("echo \"-----backup.log-------\" > "_BACKUP_LOG_FILE);
    system("cat *.log >> "_BACKUP_LOG_FILE);
    system("echo \"-----backup.log end-------\" >> "_BACKUP_LOG_FILE);
}
static int isLoader_Running(){
    int ret = 0;
    int run_st = 0, sleep_st = 0;

    run_st = get_process_state_count(ONU_LOADER_EXE, "R");
    sleep_st = get_process_state_count(ONU_LOADER_EXE, "S");

    if(run_st == 0 && sleep_st == 0){
        ret = 0;
    }else{
        ret = 1;
    }

    log_trace("isLoader_Running:%d", ret);
    
    return ret;
}
int main(int argc, char const *argv[])
{
	int zombie_count = 0, running_count = 0, sleep_count = 0;
	char exec_name[32] = {0};

    sleep(2);

	if(get_process_count(getpid()) > 1){
        get_exec_name_by_pid(getpid(), exec_name);
		fprintf(stderr,"There is a %s running...\n", exec_name);
		return 0;
	}

    if (0 > opt_parse(opts, sizeof(opts), argc, argv)) {
        return 1;
    }

    server_addr_to_ipstr(Svr_host);

    set_sig_block();

    init_log_by_self("monitor.log", "trace", "10000");

	Zombie_State_Count = get_process_state_count(ONU_PROBE_EXE, "Z");

	while(1){

		sleep(10);
        //loader运行的时候会自动下载和启动探针，monitor就不负责启动探针。
        if(!isLoader_Running()){
            running_count = get_process_state_count(ONU_PROBE_EXE, "R");
            sleep_count = get_process_state_count(ONU_PROBE_EXE, "S");
            log_trace("running:%d, sleep_count:%d", running_count, sleep_count);
            if(running_count == 0 && sleep_count == 0){
                log_trace("start "ONU_PROBE_EXE"...");
                start_onuProbe();
                exit(0);
            }
        }
        

		zombie_count = get_process_state_count(ONU_PROBE_EXE, "Z");
		log_trace("zombie_count:%d, Zombie_State_Count:%d", zombie_count, Zombie_State_Count);
		if(zombie_count > Zombie_State_Count){
            _backup_log();
            killall_process(ONU_PROBE_EXE);
            if(!isLoader_Running()){
                log_trace("start "ONU_PROBE_EXE"...");
                start_onuProbe();
            }
            exit(0);
		}
	}
	return 0;
}